<?php

/**
 * Extended from SoapClient Class to allow setting time out for calls using cURL
 * Reason & copyright: http://www.darqbyte.com/2009/10/21/timing-out-php-soap-calls/
 *
 * Edited by deathemperor, checking cURL lib
 *
 * @version $Id: SoapClient.php 1413 2012-02-29 07:10:26Z locth $
 * @author $Author: locth $
 *
 */
class SGN_SoapClient extends SoapClient
{
    /**
     *
     * @var integer
     */
    private $timeout;

    /**
     *
     * Timeout in seconds
     *
     * @param integer $timeout
     */
    public function __setTimeout($timeout)
    {
        $timeout = intval($timeout);
        if (! is_int($timeout) && ! is_null($timeout)) {
            throw new Exception("Invalid timeout value");
        }
        $this->timeout = $timeout;
    }

    /**
     * Performs SOAP request over HTTP.
     * Overridden to implement timeout request
     *
     * @param string $request
     * @param string $location
     * @param string $action
     * @param int    $version
     * @param int    $one_way
     * @return mixed
     */
    public function __doRequest($request, $location, $action, $version, $one_way = FALSE)
    {
        $startTime = microtime(true);
        if (! $this->timeout) {
            $type = 'soap';
            // Call via parent because we require no timeout
            $response = parent::__doRequest($request, $location, $action, $version, $one_way);
        } else {
            $type = 'cUrl';
            if (! function_exists('curl_init')) {
                throw new Exception("Timeout setting can only be used with cURL");
            }
            // Call via Curl and use the timeout
            $curl = curl_init($location);
            curl_setopt($curl, CURLOPT_VERBOSE, FALSE);
            curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE);
            curl_setopt($curl, CURLOPT_POST, TRUE);
            curl_setopt($curl, CURLOPT_POSTFIELDS, $request);
            curl_setopt($curl, CURLOPT_HEADER, FALSE);
            curl_setopt($curl, CURLOPT_HTTPHEADER, array("Content-Type: text/xml", "SOAPAction: {$action}"));
            curl_setopt($curl, CURLOPT_TIMEOUT, $this->timeout);
            curl_setopt($curl, CURLOPT_NOPROGRESS, FALSE);
            curl_setopt($curl, CURLOPT_FOLLOWLOCATION, TRUE);
            $response = curl_exec($curl);
            if (curl_errno($curl)) {
                throw new Exception(curl_error($curl));
            }
            curl_close($curl);
        }
        if (SGN_Application::isRegistered('profiler')) {
            $trace = debug_backtrace();
            $calledBy = "called by " . $trace[1]['file'] . ", line: " . $trace[1]['line'];;
            $totalTime = (microtime(true) - $startTime) * 1000; // in miliseconds
            SGN_Application::get('profiler')->setProfilerData('api', array("$location $calledBy", $totalTime));
        }
        // Return?
        if (! $one_way) {
            return ($response);
        }
    }
}